package org.rc.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.rc.dto.*;
import org.rc.entity.*;
import org.rc.service.*;
import org.rc.util.Md5Util;
import org.rc.util.PinyinHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;

    @Autowired
    UserRoleService userRoleService;

    @Autowired
    RoleMenuService roleMenuService;

    @Autowired
    MenuService menuService;

    @Autowired
    RoleService roleService;

    @Autowired
    UserRoomService userRoomService;

    @Autowired
    DczMemberService dczMemberService;

    @Value("${user.default.pwd}")
    private String defaultPwd;


    @PutMapping("")
    public Res addUser(@RequestBody UserAddDto userAddDto){
        if(StringUtils.isEmpty(userAddDto.getName())){
            return Res.failure("用户名不能为空");
        }
        if(StringUtils.isEmpty(userAddDto.getLoginName())){
            return Res.failure("账号不能为空");
        }
        User user = userService.getByLoginName(userAddDto.getLoginName());
        if(null != user){
            return Res.failure("账号已存在，请重新输入账号");
        }
        User addUser = userService.addUser(userAddDto);
        if(CollectionUtil.isNotEmpty(userAddDto.getRoleIds())){
            userRoleService.batchSave(userAddDto.getRoleIds().stream().map(roleId->{
                UserRole userRole = new UserRole();
                userRole.setRoleId(roleId);
                userRole.setUserId(addUser.getId());
                return userRole;
            }).collect(Collectors.toList()));
        }
        return Res.success();
    }

    @PutMapping("/dcz")
    public Res addDcz(@RequestBody DczAddDto dczAddDto){
        if(StringUtils.isEmpty(dczAddDto.getName())){
            return Res.failure("用户名不能为空");
        }
        if(StringUtils.isEmpty(dczAddDto.getLoginName())){
            return Res.failure("账号不能为空");
        }
        User user = userService.getByLoginName(dczAddDto.getLoginName());
        if(null != user){
            return Res.failure("账号已存在，请重新输入账号");
        }
        User dcz = userService.addUser(dczAddDto.getName(),dczAddDto.getLoginName());
        UserRole userRole = new UserRole();
        userRole.setUserId(dcz.getId());
        userRole.setRoleId(2L);

        userRoleService.saveUserRole(userRole);

        List<DczAddDto.Member> members = dczAddDto.getMembers();
        if(!CollectionUtils.isEmpty(members)){
            dczMemberService.batchAdd(members.stream().map(member -> {
                DczMember dczMember = DczMember.getInstance(member);
                dczMember.setDczId(dcz.getId());
                return dczMember;
            }).collect(Collectors.toList()));
        }
        return Res.success();
    }

    @PostMapping("")
    public Res updateUser(@RequestBody UserUpdateDto userUpdateDto){
        if(StringUtils.isEmpty(userUpdateDto.getName())){
            return Res.failure("用户名不能为空");
        }
        if(StringUtils.isEmpty(userUpdateDto.getLoginName())){
            return Res.failure("账号不能为空");
        }
        User user = userService.getByLoginName(userUpdateDto.getLoginName(),userUpdateDto.getId());
        if(null != user){
            return Res.failure("账号已存在，请重新输入账号");
        }
        userService.updateUser(userUpdateDto);
        if(CollectionUtil.isNotEmpty(userUpdateDto.getRoleIds())){
            userRoleService.deleteByUserId(userUpdateDto.getId());
            userRoleService.batchSave(userUpdateDto.getRoleIds().stream().map(roleId-> UserRole.getInstance(user.getId(),roleId)).collect(Collectors.toList()));
        }
        return Res.success();
    }

    @PostMapping("/dcz")
    public Res updateDcz(@RequestBody DczUpdateDto dczUpdateDto){
        if(StringUtils.isEmpty(dczUpdateDto.getName())){
            return Res.failure("用户名不能为空");
        }
        if(StringUtils.isEmpty(dczUpdateDto.getLoginName())){
            return Res.failure("账号不能为空");
        }
        User user = userService.getByLoginName(dczUpdateDto.getLoginName(),dczUpdateDto.getId());
        if(null != user){
            return Res.failure("账号已存在，请重新输入账号");
        }
        userService.updateUserById(User.getInstance(dczUpdateDto));
        List<DczUpdateDto.Member> members = dczUpdateDto.getMembers();
        if(CollectionUtil.isNotEmpty(members)){
            dczMemberService.deleteByDczId(dczUpdateDto.getId());
            dczMemberService.batchAdd(members.stream().map(member -> {
                DczMember dczMember = DczMember.getInstance(member);
                dczMember.setDczId(dczUpdateDto.getId());
                return dczMember;
            }).collect(Collectors.toList()));
        }
        return Res.success();
    }

    @DeleteMapping("/{id}")
    public Res deleteUser(@PathVariable(value = "id") Long id){
        //逻辑删除用户
        User user = userService.getByUserId(id);
        user.setIsDeleted(2);
        userService.updateUserById(user);
        //删除用户角色
        userRoleService.deleteByUserId(id);
        //更新用户房间使用记录
        List<UserRoom> userRooms = userRoomService.getByUserIds(Arrays.asList(id));
        LocalDateTime unbindTime = LocalDateTime.now();
        userRooms.forEach(userRoom -> userRoom.setUnbindTime(unbindTime));
        userRoomService.updateBatch(userRooms);
        return Res.success();
    }

    @DeleteMapping("")
    public Res batchDeleteUsers(@RequestBody UserBatchRemoveDto userBatchRemoveDto){
        //更新用户状态
        List<User> users = userService.getByUserIds(userBatchRemoveDto.getIds());
        users.forEach(user->user.setIsDeleted(2));
        userService.batchUpdateUsers(users);
        //删除用户角色绑定关系
        userRoleService.deleteByUserIds(userBatchRemoveDto.getIds());
        //更新用户房间使用记录
        List<UserRoom> userRooms = userRoomService.getByUserIds(userBatchRemoveDto.getIds());
        LocalDateTime unbindTime = LocalDateTime.now();
        userRooms.forEach(userRoom -> userRoom.setUnbindTime(unbindTime));
        userRoomService.updateBatch(userRooms);
        return Res.success();
    }

    @PostMapping("/login")
    public Res login(@RequestBody LoginDto dto){
        if(StringUtils.isEmpty(dto.getLoginName())){
            return Res.failure("登录名不能为空");
        }

        if(StringUtils.isEmpty(dto.getPassword())){
            return Res.failure("密码不能为空");
        }
        User user = userService.login(dto.getLoginName(),dto.getPassword());
        if(null == user){
            return Res.failure("登录名或密码错误");
        }
        if(user.getIsDeleted() ==2){
            return Res.failure("用户在系统中不存在");
        }
        LoginRes loginRes = LoginRes.getInstance(user);
        List<UserRole> userRoles = userRoleService.selectByUserId(user.getId());
        List<MenuDto> menuDtos = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(userRoles)){
            List<Long> roleIds = userRoles.stream().map(UserRole :: getRoleId).collect(Collectors.toList());
            List<RoleMenu> menus = roleMenuService.getByRoleIds(roleIds);
            if(CollectionUtil.isNotEmpty(menus)){
                Set<Integer> menuIds = menus.stream().map(RoleMenu :: getMenuId).collect(Collectors.toSet());
                List<Menu> menuList = menuService.getMenusByIds(new ArrayList<>(menuIds));
                menuDtos = makePidTree(menuList.stream().map(MenuDto :: getInstance).collect(Collectors.toList()),0);
            }
        }
        loginRes.setMenus(menuDtos);
        return Res.success(loginRes);
    }


    private List<MenuDto> makePidTree(List<MenuDto> menuDtos, Integer pId){
        List<MenuDto> children = menuDtos.stream().filter(x->x.getPId().equals(pId)).sorted(Comparator.comparing(MenuDto :: getWeight)).collect(Collectors.toList());
        List<MenuDto> successor = menuDtos.stream().filter(x->!x.getPId().equals(pId)).collect(Collectors.toList());
        children.forEach(x -> x.setChildren(makePidTree(successor,x.getId())));
        return children;
    }


    @PostMapping("/login_name")
    public Res getLoginNameByName(@RequestParam("name") String name){
        String pinyin = PinyinHelper.getPinYin(name);
        List<User> users = userService.getSimilarAccountByLoginName(pinyin);
        String regex = "^"+pinyin+"\\d*$";
        Pattern pattern = Pattern.compile(regex);
        int sn = 0;
        for(User user : users){
            String loginName = user.getLoginName();
            if(StringUtils.isNotEmpty(loginName)){
                Matcher matcher = pattern.matcher(loginName);
                if(matcher.matches()){
                    sn++;
                }
            }
        }
        pinyin = sn>0 ? pinyin+sn:pinyin;
        return Res.success(pinyin);
    }

    @PostMapping("/pwd")
    public Res passwordConfirm(@RequestBody PwdConfirmDto pwdConfirmDto){
        if(StringUtils.isEmpty(pwdConfirmDto.getLoginName())){
            return Res.failure("登录名不能为空");
        }

        if(StringUtils.isEmpty(pwdConfirmDto.getPassword())){
            return Res.failure("密码不能为空");
        }

        User user = userService.login(pwdConfirmDto.getLoginName(),pwdConfirmDto.getPassword());
        if(null == user){
            return Res.failure("密码错误");
        }
        return Res.success();
    }

    @PostMapping("/new_pwd")
    public Res updatePassword(@RequestBody UpdatePwdDto updatePwdDto){
        Long userId = updatePwdDto.getId();
        if(null == userId){
            return Res.failure("用户不能为空");
        }
        String oldPwd = updatePwdDto.getOldPassword();

        if(StringUtils.isEmpty(oldPwd)){
            return Res.failure("旧密码不能为空");
        }

        if(StringUtils.isEmpty(updatePwdDto.getNewPassword())){
            return Res.failure("新密码不能为空");
        }
        User user = userService.getByUserId(userId);
        if(null == user){
            return Res.failure("用户不存在");
        }
        if(!oldPwd.equals(user.getPwd())){
            return Res.failure("旧密码不正确");
        }
        userService.updatePwd(updatePwdDto.getId(),updatePwdDto.getNewPassword());
        return Res.success();
    }

    @PostMapping("/page")
    public Res getUserPage(@RequestBody UserPageDto userPageDto){
        Page<User> userPage = userService.getUserPage(userPageDto);
        List<UserPageRes> userPageResList = new ArrayList<>();
        Map<Long,List<UserRole>> userRoleMap = null;
        Map<Long,Role> roleMap = null;
        if(null != userPage && !CollectionUtils.isEmpty(userPage.getRecords())){
            List<User> users = userPage.getRecords();
            List<UserRole> userRoles = userRoleService.selectByUserIds(users.stream().map(User::getId).collect(Collectors.toList()));
            if(!CollectionUtils.isEmpty(userRoles)){
                userRoleMap= userRoles.stream().collect(Collectors.groupingBy(UserRole ::getUserId));
                List<Role> roles = roleService.getByRoleIds(userRoles.stream().map(UserRole :: getRoleId).collect(Collectors.toList()));
                roleMap = roles.stream().collect(Collectors.toMap(Role :: getId, role->role));
            }

            for(User user : users){
                UserPageRes userPageRes = UserPageRes.getInstance(user);
                List<UserPageRes.RoleInfo> roles = new ArrayList<>();
                if(!CollectionUtils.isEmpty(userRoleMap) && userRoleMap.containsKey(user.getId())){
                    List<UserRole> userRoleList = userRoleMap.get(user.getId());
                    for(UserRole userRole : userRoleList){
                        if(roleMap.containsKey(userRole.getRoleId())){
                            roles.add(UserPageRes.RoleInfo.getInstance(roleMap.get(userRole.getRoleId())));
                        }
                    }
                }
                userPageRes.setRoles(roles);
                userPageResList.add(userPageRes);
            }
        }
        PageDto pageDto = PageDto.of(userPage);
        pageDto.setData(userPageResList);
        return Res.success(pageDto);
    }

    @GetMapping("/dcz/{id}")
    public Res getDczPage(@PathVariable(value = "id") Long id){
        User user = userService.getByUserId(id);
        DczInfoDto dczInfoDto = DczInfoDto.getInstance(user);
        List<DczMember> dczMembers = dczMemberService.getByDczId(id);
        if(!CollectionUtils.isEmpty(dczMembers)){
            dczInfoDto.setMembers(dczMembers.stream().map(DczInfoDto.Member :: getInstance).collect(Collectors.toList()));
        }
        return Res.success(dczInfoDto);
    }

    @GetMapping("/pwd/{id}")
    public Res resetPwd(@PathVariable(value = "id") Long id){
        User user = userService.getByUserId(id);
        user.setPwd(Md5Util.encrypt(defaultPwd));
        userService.updateUserById(user);
        return Res.success();
    }

    @GetMapping("/all_users")
    public Res getAllUsers(){
        return Res.success(userService.getAllDczUsers());
    }

    @GetMapping("/{roomId}")
    public Res getAllUsersByRoomId(@PathVariable(value = "roomId") Long roomId){
        List<User> users = new ArrayList<>();
        List<UserRoom>  userRooms = userRoomService.getUserRoomsByRoomIds(Arrays.asList(roomId));
        if(!CollectionUtils.isEmpty(userRooms)){
            users = userService.getByUserIds(userRooms.stream().map(UserRoom :: getUserId).collect(Collectors.toList()));
        }
        return Res.success(users);
    }

}
